//
// Created by 16933 on 2022/4/30.
//

#include "bsp_I2C.h"

/*! 发送开始信号
 * 该信号的判定条件：SCL高电平期间，SDA从高电平切换到低电平
 * 该信号前SCL与SDA的状态：  1.初始的时候出现：SCL、SDA空闲，被上拉，两者都为高电平(1)
 *                       2.在读取应答信号之后重新开始一帧数据时出现：此时SDA可能为高电平也可能为低电平 SCL为低电平(0)
 * 该信号后SCL与SDA的状态： SDA为0  SCL为0   总线忙
 * */

void I2C_Start()
{
    SDA_UP();               //保证SDA为高电平
    SCL_UP();
    DELAY();
    SDA_DOWN();
    DELAY();        //至少保持0.6us
    SCL_DOWN();             //钳住I2C总线，准备发送或接收
}

/*!  发送结束信号
 * 该信号的判定条件：SCL高电平期间，SDA从低电平切换到高电平
 * 该信号前SCL与SDA的状态：  1. 跟在产生应答信号之后    SDA可能是0 可能是1   我们掌握总线控制权 所以SCL为0
 *                       2. 跟在读取应答信号之后    SDA可能是0 可能是1    我们掌握总线控制权 所以SCL为0
 * 该信号后SCL与SDA的状态： SDA为1  SCL为1  符合空闲状态
 * */
void I2C_Stop()
{
    SDA_DOWN();         //保证SDA低电平从而可以产生上升沿
    SCL_UP();
    DELAY();
    SDA_UP();
    DELAY();
}


/*! 发送应答信号
 * 该信号的判定条件：SDA低电平期间 SCL拉高再拉低
 * 该信号前SCL与SDA的状态：跟在发送数据之后    SDA可能为0 可能为1， 我们掌握总线控制权 所以SCL为0
 * */
void I2C_Send_ACK()
{
    SDA_DOWN();
    SCL_UP();
    DELAY();
    SCL_DOWN();
}

/*! 发送非应答信号
 * 该信号的判定条件：SDA低电平期间 SCL拉高再拉低
 * 该信号前SCL与SDA的状态：跟在发送数据之后    SDA可能为0 可能为1， 我们掌握总线控制权 所以SCL为0
 * */
void I2C_Send_NACK()
{
    SDA_UP();
    SCL_UP();
    DELAY();
    SCL_DOWN();
}

/*! 等待应答信号 */
uint8_t I2C_Wait_ACK()
{
    uint8_t ACK = 0;
    SDA_UP();                   //释放SDA总线
    SCL_UP();                   //SCL拉高时期可以进行读取
    DELAY();                    //给它从设备点反应时间0
    ACK = SDA_READ();
    SCL_DOWN();
    return ACK;
}


/*! 发送一个字节数据 */
void I2C_Send_Byte(uint8_t Byte)
{
    uint8_t i;
    for (i=0; i < 8; i++) {
        if (Byte&(0x80>>i))     //发1   can总线上时高位先行
        {
            SDA_UP();
            SCL_UP();
            delay_us(1);  // 最低时间为0.4us  要保证可以读取到
            SCL_DOWN();
        } else                  //发0
        {
            SDA_DOWN();
            SCL_UP();
            delay_us(1);
            SCL_DOWN();
        }

    }
}


/*! 接收一个字节数据 并发送ACK*/

uint8_t I2C_Receive_Byte(uint8_t  ack)
{
    uint8_t Byte = 0x00;
    uint8_t i;
    SDA_UP();    //释放SDA总线

    for (i = 0; i < 8; i++) {
        SCL_UP();


        if (SDA_READ()) //读到1
        {

            Byte|=(0x80>>i);
        }
        SCL_DOWN();

    }
    if (!ack)
    {
        I2C_Send_NACK();

    } else
    {
        I2C_Send_ACK();
    }
    return Byte;
}



void delay_us(uint32_t us)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * us);
    while (delay--)
    {
        ;
    }
}

void delay_ms(uint32_t ms)
{
    uint32_t delay = (HAL_RCC_GetHCLKFreq() / 4000000 * (1000*ms));
    while (delay--)
    {
        ;
    }
}